package com.zhuiyun.imageserver.file.service.impl;

import com.zhuiyun.imageserver.config.VariableConfig;
import com.zhuiyun.imageserver.errorCode.CommonException;
import com.zhuiyun.imageserver.errorCode.EmErrorCode;
import com.zhuiyun.imageserver.file.entity.FileManage;
import com.zhuiyun.imageserver.file.mapper.FileManageMapper;
import com.zhuiyun.imageserver.file.service.FileManageService;
import com.zhuiyun.imageserver.response.CommonResult;
import com.zhuiyun.imageserver.utils.DateTimeUtils;
import com.zhuiyun.imageserver.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.common.Mapper;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.UUID;

/**
 * 操作图片services
 * @auther zcy
 * @data 2020/6/24 11:24
 */
@Service
public class FileManageServiceImpl  implements FileManageService {

    @Autowired
    private VariableConfig variableConfig;
    @Autowired
    FileManageMapper fileManageMapper;
    @Autowired
    Mapper<FileManage> mapper;

    /**
     * 通过id删除图片 和 数据库中的记录
     *  加事务两者必须同时成功
     * @param id
     * @return
     * @throws CommonException
     */
    @Override
    @Transactional
    public CommonResult deleteImageById(Integer id) throws CommonException {
        if (StringUtils.isNotEmpty(id)){
            FileManage fileManage = mapper.selectByPrimaryKey(id);
            // 判断对象是否存在
            if(StringUtils.isNotEmpty(fileManage)){
                // 删除图片信息
                int i = mapper.deleteByPrimaryKey(id);
                if (i <= 0) {
                    throw new CommonException(EmErrorCode.DELETE_ERROR);
                }
                // 删除图片
                File file = new File(variableConfig.getRootPath() +File.separator + fileManage.getFilePath() + File.separator + fileManage.getFileUuidName());
                file.delete();
            }else{
                throw new CommonException(EmErrorCode.OBJECT_ISNULL);
            }

        }else{
            throw new CommonException(EmErrorCode.ID_NULL);
        }
        return CommonResult.ok("删除成功!");
    }

    /**
     * 将前台接收文件保存到系统并记录文件信息
     * 数据 和 图片必须同时成功 所以添加事务
     *
     * @param file
     * @param projectName
     * @return
     */
    @Override
    @Transactional
    public FileManage saveFileToSystem(MultipartFile file, String projectName) throws CommonException {
        FileManage fileManage = null;
        // 判断file对象是否为空
        if (StringUtils.isNotEmpty(file)) {
            //文件路径
            String fileAllPath = "";
            //获取文件名称
            String filename = file.getOriginalFilename();
            // 获取文件后缀名称
            int begin = filename.indexOf(".");
            int last = filename.length();
            String fileType = filename.substring(begin, last);
            //文件大小
            long fileSize = file.getSize();
            // 拼接时间文件夹
            String format = DateTimeUtils.format("yyyyMMdd",new Date());
            // 加密文件名称
            String fileUuidName = "";
            // 文件路径
            String filePath = "";
            //判断文件类型并校验大小是否超出范围
            if (variableConfig.getImageType().contains(fileType)) {
                if (fileSize > variableConfig.getImageSize()*1024*1024) {
                    // 抛出文件大小超出范围异常
                    throw new CommonException(EmErrorCode.IMAGE_SIZE_ERROR);
                }
                // 项目名称 + path + 时间格式
                filePath = projectName + File.separator + variableConfig.getImagePath()+ File.separator + format;
           // 判断是否是文件 如txt excel
            }  else if (variableConfig.getFileType().contains(fileType)) {
                if (fileSize > variableConfig.getFileSize()*1024*1024) {
                    // 抛出文件大小超出范围异常
                    throw new CommonException(EmErrorCode.FILE_SIZE_ERROR);
                }
                // 项目名称 + path + 时间格式
                filePath = projectName + File.separator + variableConfig.getFilePath()+ File.separator + format;
            } else if (variableConfig.getVideoType().contains(fileType)) {
                if (fileSize > variableConfig.getVideoSize()*1024*1024) {
                    // 抛出文件大小超出范围异常
                    throw new CommonException(EmErrorCode.VIDEO_SIZE_ERROR);
                }
                // 项目名称 + path + 时间格式
                filePath = projectName + File.separator + variableConfig.getVideoPath()+ File.separator + format;
            } else {
                // 抛出文件类型错误异常
                throw new CommonException(EmErrorCode.FILE_TYPE_ERROR, "附件类型错误,目前只支持附件类型为:" + variableConfig.getImageType()+variableConfig.getFileType()+variableConfig.getVideoType());
            }
            // 将uuid中‘-’去掉
            fileUuidName = UUID.randomUUID().toString().replace("-","") + fileType;
            // 拼接图片全路径
            fileAllPath = variableConfig.getRootPath()+ File.separator + filePath + File.separator + fileUuidName;
            // 将文件信息封装到对象并保存早数据库
            fileManage = new FileManage();
            fileManage.setFileName(filename);
            fileManage.setFileUuidName(fileUuidName);
            fileManage.setFileType(fileType);
            fileManage.setFileSize(fileSize + "");
            fileManage.setFilePath(filePath);
            fileManage.setCreateTime(new Date());
            // 保存对象
            fileManageMapper.insert(fileManage);
            // 数据存储成功后将图片存入磁盘
            if(fileManage.getId()>0){
                // 创建 File对象
                File targetFile = new File(fileAllPath);
                //判断文件所在文件夹是否存在
                if (!targetFile.getParentFile().exists()) {
                    //不存在就创建文件夹
                    targetFile.getParentFile().mkdirs();
                }
                try {
                    // 将文件写入系统磁盘
                    file.transferTo(targetFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileManage;
    }

    /**
     * 下载图片
     * @param response
     * @param id
     */
    @Override
    public void getImage(HttpServletResponse response, Integer id) throws CommonException {
        if(StringUtils.isNotEmpty(id)){
            // 获取我呢见对象
            FileManage fileManage = mapper.selectByPrimaryKey(id);
            if(fileManage!=null&&variableConfig.getImageType().contains(fileManage.getFileType())){
                // 拼接图片路径
                File file = new File(variableConfig.getRootPath() + File.separator + fileManage.getFilePath() + File.separator + fileManage.getFileUuidName());
                if(file.exists()){
                    FileInputStream fis = null;
                    OutputStream os = null;
                    try {
                        // 将图片读取到文件输入流中
                        fis = new FileInputStream(file);
                        byte[] data = new byte[(int) file.length()];
                        fis.read(data);
                        response.setContentType("image/png;charset=utf-8");
                        // 获取输出流对象
                        os = response.getOutputStream();
                        // 写入
                        os.write(data);
                        os.flush();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        // 关闭流
                        closeIO(os,fis);
                    }
                }else{
                    throw new CommonException(EmErrorCode.IMAGE_NOT_EXISTS);
                }
            }else{
                throw new CommonException(EmErrorCode.IMAGE_NOT_EXISTS);
            }
        }else {
            throw new CommonException(EmErrorCode.ID_NULL);
        }
    }

    /**
     * 通过url获取网络图片
     * @param response
     * @param urlPath
     */
    @Override
    public void getImageByUrl(HttpServletResponse response, String urlPath) {
        URL url = null;
        try {
            // 创建连接
            url = new URL(urlPath);
            DataInputStream dataInputStream = new DataInputStream(url.openStream());
            response.setContentType("image/png;charset=utf-8");
            OutputStream stream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = dataInputStream.read(buffer)) > 0) {
                stream.write(buffer, 0, length);
            }
            stream.flush();
            stream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载文件
     * @param response
     * @param id
     */
    @Override
    public void getFileById(HttpServletResponse response, Integer id) throws CommonException {
        if(StringUtils.isNotEmpty(id)){
            // 获取我呢见对象
            FileManage fileManage = mapper.selectByPrimaryKey(id);
            if(fileManage!=null&&variableConfig.getFileType().contains(fileManage.getFileType())){
                // 拼接图片路径
                File file = new File(variableConfig.getRootPath() + File.separator + fileManage.getFilePath() + File.separator + fileManage.getFileUuidName());
                if(file.exists()){
                    FileInputStream fis = null;
                    OutputStream os = null;
                    try {
                        response.setContentType("application/octet-stream;charset=UTF-8");
                        String fileName = new String(fileManage.getFileName().getBytes(), "iso8859-1");
                        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
                        // 将图片读取到文件输入流中
                        fis = new FileInputStream(file);
                        byte[] data = new byte[(int) file.length()];
                        fis.read(data);
                        // 获取输出流对象
                        os = response.getOutputStream();
                        // 写入
                        os.write(data);
                        os.flush();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        // 关闭流
                        closeIO(os,fis);
                    }
                }else{
                    throw new CommonException(EmErrorCode.FILE_NOT_EXISTS);
                }
            }else {
                throw new CommonException(EmErrorCode.FILE_NOT_EXISTS);
            }
        }else {
            throw new CommonException(EmErrorCode.ID_NULL);
        }
    }

    /**
     * 下载视频
     * @param response
     * @param id
     */
    @Override
    public void getVideoById(HttpServletResponse response, Integer id) throws CommonException, FileNotFoundException {
        if(StringUtils.isNotEmpty(id)){
            // 获取我呢见对象
            FileManage fileManage = mapper.selectByPrimaryKey(id);
            if(fileManage!=null&&variableConfig.getVideoType().contains(fileManage.getFileType())){
                // 拼接图片路径
                File file = new File(variableConfig.getRootPath() + File.separator + fileManage.getFilePath() + File.separator + fileManage.getFileUuidName());
                if(file.exists()){
                    RandomAccessFile targetFile = new RandomAccessFile(file, "r");
                    OutputStream os = null;
                    try {
                        //设置响应头，把文件名字设置好
                        response.setContentType("application/octet-stream;charset=UTF-8");
                        String fileName = new String(fileManage.getFileName().getBytes(), "iso8859-1");
                        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
                        //设置文件长度
                        response.setHeader("Content-Length", String.valueOf(fileManage.getFileSize()));
                        //解决编码问题

                        byte[] cache = new byte[(int) file.length()];
                        // 获取输出流
                        os = response.getOutputStream();
                        int flag;
                        while ((flag = targetFile.read(cache))!=-1){
                            os.write(cache, 0, flag);
                        }
                        os.flush();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        // 关闭流
                        closeIO(os,null);
                    }
                }else{
                    throw new CommonException(EmErrorCode.VIDEO_NOT_EXISTS);
                }
            }else{
                throw new CommonException(EmErrorCode.VIDEO_NOT_EXISTS);
            }
        }else {
            throw new CommonException(EmErrorCode.ID_NULL);
        }

    }

    /**
     * 关闭 输出输入流
     * @param os
     * @param fis
     */
    public void closeIO(OutputStream os,FileInputStream fis){
        // 关闭文件输入流
        if(fis!=null){
            try {
                fis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // 关闭输出流
        if(os!=null){
            try {
                os.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
